/**
 * Array is a heap-allocated, length-prefixed, fixed-length collection type.
 */
abstract Array[T]: Slice[T] {
    public static function new(allocator: Box[Allocator], length: Size): Self {
        var data: Ptr[T] = allocator.calloc(sizeof T * length);
        return struct Self {
            length,
            data,
        };
    }

    public function blit(other: Ptr[Array[T]], start: Size, length: Size): Void {
        memcpy(&(other.data[start]) as Ptr[Void], this.data as Ptr[Void], length * sizeof T);
    }

    public function copy(allocator: Box[Allocator]): Array[T] using implicit allocator {
        var a = Self.new(this.length);
        this.blit(a, 0, this.length);
        return a;
    }

    public function free(allocator: Box[Allocator]) {
        allocator.free(this.data);
    }

    public function all(fn: function (&T) -> Bool): Bool {
        for item in this {
            if !fn(item) {
                return false;
            }
        }
        return true;
    }

    public function any(fn: function (&T) -> Bool): Bool {
        for item in this {
            if fn(item) {
                return true;
            }
        }
        return false;
    }
}
